package csvr

import (
	"encoding/json"
	"fmt"
	"iot-base/common/tunnel/protocol"
	"iot-base/common/tunnel/udp"
	"net"
	"time"
)

type Addr struct {
	IP   string
	Port int
}

type Info struct {
	pAddr    *net.UDPAddr
	lastTime int64
}

type CHandler struct {
	mapAddrs   map[string]Info
	mapClients map[string][]Info
	seq        uint32
	port       int
	sendBuffer [1024]byte
}

func (pHandler *CHandler) Seq() uint32 {
	return pHandler.seq
}
func (pHandler *CHandler) Port() int {
	return pHandler.port
}

//EdgeDetail 边缘节点信息
type EdgeDetail struct {
	ID       string
	LastTime string
}

func (pHandler *CHandler) OnData(data []byte, pHeader *protocol.Header, nlen int, conn *net.UDPConn, addr *net.UDPAddr) {

	switch pHeader.Ptype {
	case protocol.HB:
		if nlen > 5 {
			id := string(pHeader.Body)
			pHandler.mapAddrs[id] = Info{
				pAddr:    addr,
				lastTime: time.Now().Unix(),
			}
			fmt.Println("save edge----", id)
		}
	case protocol.WAKEUP:
		if nlen > 5 {
			//id :=
			pEdgeAddr, ok := pHandler.mapAddrs[string(pHeader.Body)]
			if ok {
				now := time.Now().Unix()
				pHeader.Ptype = protocol.BEGIN
				if now-pEdgeAddr.lastTime < 40 {
					//addrs := fmt.Sprintf("%s:%d", pEdgeAddr.pAddr.IP, pEdgeAddr.pAddr.Port)
					//pHeader.Body = []byte(addrs)
					//slen, _ := pHeader.ToBuffer(pHandler.sendBuffer[0:])
					//conn.WriteToUDP(pHandler.sendBuffer[0:slen], addr)
					pclients := pHandler.mapClients[string(pHeader.Body)]
					isFound := false
					if pclients != nil {
						j := 0
						for _, pc := range pclients {
							//pc := pclients[i]
							if string(pc.pAddr.IP) == string(addr.IP) && pc.pAddr.Port == addr.Port {
								pc.lastTime = now
								isFound = true
								pclients[j] = pc
								j++
							} else if now-pc.lastTime < 40 {
								pclients[j] = pc
								j++
							}
						}
						pHandler.mapClients[string(pHeader.Body)] = pclients[:j]

					}
					if !isFound {
						if pclients == nil {
							pclients = make([]Info, 0, 1)
						}
						pclients = append(pclients, Info{
							pAddr:    addr,
							lastTime: now,
						})
						fmt.Println("add pclients to pclients map")
						pHandler.mapClients[string(pHeader.Body)] = pclients
					}
					pHeader.Body = []byte(fmt.Sprintf("%s:%d", addr.IP, addr.Port))
					slen, _ := pHeader.ToBuffer(pHandler.sendBuffer[0:])
					conn.WriteToUDP(pHandler.sendBuffer[0:slen], pEdgeAddr.pAddr) //向边缘，假设边缘的网络条件是net型
					fmt.Println("sendback to  edge---client count----", len(pclients))
				} else {
					delete(pHandler.mapAddrs, string(pHeader.Body))
					fmt.Println("edge info too old remove")
				}

			} else {
				fmt.Println("edge not found---id-----", string(pHeader.Body))
			}
		}
	case protocol.WAKEUP_RES:
		pclients := pHandler.mapClients[string(pHeader.Body)]
		for _, pc := range pclients {
			//pc := pclients[i]
			pHeader.Ptype = protocol.BEGIN
			saddr := fmt.Sprintf("%s:%d", addr.IP, addr.Port)
			fmt.Println("send to client ---------", saddr, pc.pAddr)
			pHeader.Body = []byte(saddr)
			slen, _ := pHeader.ToBuffer(pHandler.sendBuffer[0:])
			conn.WriteToUDP(pHandler.sendBuffer[0:slen], pc.pAddr)
			fmt.Println("send to client begin--------", pc.pAddr)

		}
		fmt.Println("get len:", len(pclients))

	case protocol.GETLIST:
		{
			var ids = make([]EdgeDetail, 0)
			fmt.Println("getlist-----------", len(pHandler.mapAddrs))
			for id, info := range pHandler.mapAddrs {
				now := time.Now().Unix()
				if now-info.lastTime < 40 {

					ids = append(ids, EdgeDetail{
						ID:       id,
						LastTime: time.Unix(info.lastTime, 0).Format("2006.01.02 15:04:05"),
					})
				} else {
					fmt.Println("remove-----------", id)
					delete(pHandler.mapAddrs, id)
				}
			}
			buf, _ := json.Marshal(ids)
			conn.WriteToUDP(buf, addr)

		}

	}

}

func BeginSvr(port int) {
	udp.Begin(port, &CHandler{port: port, mapAddrs: make(map[string]Info), mapClients: make(map[string][]Info)})
}
